package com.bytedance.douyinclouddemo.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.bytedance.douyinclouddemo.model.JsonResponse;
import com.bytedance.douyinclouddemo.model.LiveDataModel;
import com.bytedance.douyinclouddemo.model.LivePlayAPIResponse;
import com.bytedance.douyinclouddemo.service.MyRedisService;
import lombok.extern.slf4j.Slf4j;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 抖音云x弹幕玩法的服务端demo展示
 */
@RestController
@Slf4j
public class LivePlayDemoController {

    private String appId;
    private String appSecret;

    private boolean isOnlineVersion;

    private String worldRankVersion;

    public LivePlayDemoController() {
        this.appId = "tt5c3e2a83c30f1d8910";
        this.appSecret = "9e8524c971573540c0cb1809d7fc5d83e3949654";
        this.isOnlineVersion = false;
        this.worldRankVersion = this.appId+new SimpleDateFormat("yyyyMMdd").format(new Date());

    }

    @Autowired
    private MyRedisService myRedisService;

    /**
     * 开始玩法对局，玩法开始前调用
     */
    @PostMapping(path = "/start_game")
    public JsonResponse callContainerExample(HttpServletRequest httpRequest) {
        // 开发者可以直接通过请求头获取直播间信息,无需自行通过token置换

        // 应用id
        String appID = httpRequest.getHeader("X-TT-AppID");
        // 直播间id
        String roomID = httpRequest.getHeader("X-Room-ID");
        // 主播id
        String anchorOpenID = httpRequest.getHeader("X-Anchor-OpenID");
        // 主播头像url
        String avatarUrl = httpRequest.getHeader("X-Avatar-Url");
        // 主播昵称
        String nickName = httpRequest.getHeader("X-Nick-Name");

        log.info("appID: {}, roomID: {}, anchorOpenID: {}, avatarUrl: {}, nickName: {}", appID,
                roomID, anchorOpenID, avatarUrl, nickName);


        // 调用弹幕玩法服务端API，开启直播间推送任务，开启后，开发者服务器会通过/live_data_callback接口 收到直播间玩法指令
        List<String> msgTypeList = new ArrayList<>();
        msgTypeList.add("live_like");
        msgTypeList.add("live_comment");
        msgTypeList.add("live_gift");
        msgTypeList.add("live_fansclub");

        for (String msgType : msgTypeList) {
            boolean result = startLiveDataTask(appID, roomID, msgType);
            if (result) {
                log.info("{} 推送开启成功", msgType);
            } else {
                log.error("{} 推送开启失败", msgType);
            }
        }

        JsonResponse response = new JsonResponse();
        response.success("开始玩法对局成功");
        return response;
    }

    /**
     * startLiveDataTask: 开启推送任务：<a href="https://developer.open-douyin.com/docs/resource/zh-CN/interaction/develop/server/live/danmu#%E5%90%AF%E5%8A%A8%E4%BB%BB%E5%8A%A1">...</a>
     *
     * @param appID   小玩法appID
     * @param roomID  直播间ID
     * @param msgType 评论/点赞/礼物/粉丝团
     */
    private boolean startLiveDataTask(String appID, String roomID, String msgType) {
        // example: 通过java OkHttp库发起http请求,开发者可使用其余http访问形式
        OkHttpClient client = new OkHttpClient();
        String body = new JSONObject()
                .fluentPut("roomid", roomID)
                .fluentPut("appid", appID)
                .fluentPut("msg_type", msgType)
                .toString();
        Request request = new Request.Builder()
                .url("http://webcast.bytedance.com/api/live_data/task/start") // 内网专线访问小玩法openAPI,无需https协议
                .addHeader("Content-Type", "application/json") // 无需维护access_token
                .post(
                        okhttp3.RequestBody.create(
                                MediaType.get("application/json; charset=utf-8"),
                                body
                        )
                )
                .build();

        try {
            Response httpResponse = client.newCall(request).execute();
            if (httpResponse.code() != 200) {
                log.error("开启推送任务失败,http访问非200");
                return false;
            }
            LivePlayAPIResponse livePlayAPIResponse
                    = JSON.parseObject(httpResponse.body().string(), LivePlayAPIResponse.class);
            if (livePlayAPIResponse.getErrNo() != 0) {
                log.error("开启推送任务失败，错误信息: {}", livePlayAPIResponse.getErrorMsg());
                return false;
            }
        } catch (IOException e) {
            log.error("开启推送任务异常,e: {}", e.getMessage(), e);
            return false;
        }
        return true;
    }

    /**
     * 结束玩法
     */
    @PostMapping(path = "/finish_game")
    public JsonResponse finishGameExample(HttpServletRequest httpRequest) {
        // TODO: 玩法对局结束,开发者自行实现对局结束逻辑
        JsonResponse response = new JsonResponse();
        response.success("结束玩法成功");
        return response;
    }


    /**
     * 通过抖音云服务接受直播间数据，内网专线加速+免域名备案
     * 通过内网专线会自动携带X-Anchor-OpenID字段
     * ref: <a href="https://developer.open-douyin.com/docs/resource/zh-CN/developer/tools/cloud/develop-guide/danmu-callback">...</a>
     */
    @PostMapping(path = "/live_data_callback")
    public JsonResponse liveDataCallbackExample(
            @RequestHeader("X-Anchor-OpenID") String anchorOpenID,
            @RequestHeader("x-msg-type") String msgType,
            @RequestBody String body) {
        List<LiveDataModel> liveDataModelList = JSON.parseArray(body, LiveDataModel.class);
        liveDataModelList.forEach(liveDataModel ->
                pushDataToClientByDouyinCloudWebsocket(anchorOpenID, liveDataModel.getMsgID(), msgType, body)
        );
        JsonResponse response = new JsonResponse();
        response.success("success");
        return response;
    }


    //---------------- 抖音云websocket相关demo ---------------------

    /**
     * 抖音云websocket监听的回调函数,客户端建连/上行发消息都会走到该HTTP回调函数中
     * ref: <a href="https://developer.open-douyin.com/docs/resource/zh-CN/developer/tools/cloud/develop-guide/websocket-guide/websocket#%E5%BB%BA%E8%BF%9E%E8%AF%B7%E6%B1%82">...</a>
     */
    @RequestMapping(path = "/websocket_callback", method = {RequestMethod.POST, RequestMethod.GET})
    public JsonResponse websocketCallback(HttpServletRequest request) {
        String eventType = request.getHeader("x-tt-event-type");
        switch (eventType) {
            case "connect":
                // 客户端建连
            case "disconnect": {
                // 客户端断连
            }
            case "uplink": {
                // 客户端上行发消息
            }
            default:
                break;
        }
        JsonResponse response = new JsonResponse();
        response.success("success");
        return response;
    }

    /**
     * 使用抖音云websocket网关,将数据推送到主播端
     * ref: <a href="https://developer.open-douyin.com/docs/resource/zh-CN/developer/tools/cloud/develop-guide/websocket-guide/websocket#%E4%B8%8B%E8%A1%8C%E6%B6%88%E6%81%AF%E6%8E%A8%E9%80%81">...</a>
     */
    private void pushDataToClientByDouyinCloudWebsocket(String anchorOpenId, String msgID, String msgType, String data) {
        // 这里通过HTTP POST请求将数据推送给抖音云网关,进而抖音云网关推送给主播端
        OkHttpClient client = new OkHttpClient();

        Map<String, String> bodyMap = new HashMap<>();
        bodyMap.put("msg_id", msgID);
        bodyMap.put("msg_type", msgType);
        bodyMap.put("data", data);
//        bodyMap.put("extra_data", "");
        String bodyStr = JSON.toJSONString(bodyMap);

        Request request = new Request.Builder()
                .url("http://ws-push.dycloud-api.service/ws/live_interaction/push_data")
                .addHeader("Content-Type", "application/json")
                .addHeader("X-TT-WS-OPENIDS", JSON.toJSONString(Arrays.asList(anchorOpenId)))
                .post(
                        okhttp3.RequestBody.create(
                                MediaType.parse("application/json; charset=utf-8"),
                                bodyStr
                        )
                )
                .build();

        try {
            Response httpResponse = client.newCall(request).execute();
            log.info("websocket http call done, response: {}", JSON.toJSONString(httpResponse));
        } catch (IOException e) {
            log.error("websocket http call exception, e: ", e);
        }
    }



    /**
     * 设置榜单生效版本
     * @param httpRequest
     * @return
     */
    @PostMapping(path = "/set_valid_version")
    public JsonResponse setValidVersion(HttpServletRequest httpRequest){
        JsonResponse response = new JsonResponse();

        String token = getAccessToken();

        OkHttpClient client = new OkHttpClient();

        Map<String, Object> bodyMap = new HashMap<>();
        bodyMap.put("app_id", appId);
        bodyMap.put("is_online_version", isOnlineVersion);
        bodyMap.put("world_rank_version", worldRankVersion);
        String bodyStr = JSON.toJSONString(bodyMap);

        Request request = new Request.Builder()
                .url("https://webcast.bytedance.com/api/gaming_con/world_rank/set_valid_version")
                .addHeader("Content-Type", "application/json")
                .addHeader("X-Token", token)
                .post(
                        okhttp3.RequestBody.create(
                                MediaType.parse("application/json; charset=utf-8"),
                                bodyStr
                        )
                )
                .build();
        try {
            Response httpResponse = client.newCall(request).execute();
            if (!httpResponse.isSuccessful()) {
                log.error("设置世界榜单失败，HTTP响应码: {}", httpResponse.code());
                response.failure("设置世界榜单失败，HTTP响应码: " + httpResponse.code());
                return response;
            }
            String responseBody = httpResponse.body().string();
            JSONObject jsonResponse = JSON.parseObject(responseBody);
            // 判断 errcode
            int errcode = jsonResponse.getInteger("errcode");
            if (errcode == 0) {
                //将当前世界榜单存入redis
                myRedisService.setValue("world_rank_version_" + appId, worldRankVersion);
                response.success("设置世界榜单成功");
            } else {
                String errmsg = jsonResponse.getString("errmsg");
                log.error("设置世界榜单失败，错误信息: {}", errmsg);
                response.failure(errmsg);
            }
        } catch (IOException e) {
            log.error("设置世界榜单失败, e: ", e);
        }

        return response;
    }

    /**
     * 上传世界榜单列表数据
     * @param httpRequest
     * {
     *     "rank_list": "[{\"open_id\":\"user1\",\"rank\":1,\"score\":100,\"winning_streak_count\":5,\"winning_points\":50},{\"open_id\":\"user2\",\"rank\":2,\"score\":90,\"winning_streak_count\":3,\"winning_points\":30}]"
     * }
     * @return
     */
    @PostMapping(path = "/upload_rank_list")
    public JsonResponse uploadRankList(HttpServletRequest httpRequest){
        JsonResponse response = new JsonResponse();
        String token = getAccessToken();
        OkHttpClient client = new OkHttpClient();

        String worldRankVersion = (String)myRedisService.getValue("world_rank_version_" + appId);
        if(worldRankVersion == null){
            response.failure("世界榜单未设置，请先调用接口/set_valid_version，设置世界榜单");
            return response;
        }

        // 从请求体中获取 rank_list 参数
        StringBuilder jsonBuilder = new StringBuilder();
        try (BufferedReader reader = httpRequest.getReader()) {
            String line;
            while ((line = reader.readLine()) != null) {
                jsonBuilder.append(line);
            }
        } catch (IOException e) {
            response.failure("json数据不正确");
            return response;
        }

        String requestBody = jsonBuilder.toString();
        if (requestBody.isEmpty()) {
            response.failure("请求体不能为空，未传递 JSON 数据");
            return response;
        }
        JSONObject requestJson = JSON.parseObject(requestBody);
        String rankListJson = requestJson.getString("rank_list");
        if (rankListJson == null || rankListJson.isEmpty()) {
            response.failure("缺少排名列表数据");
            return response;
        }


        Map<String, Object> bodyMap = new HashMap<>();
        bodyMap.put("app_id", appId);
        bodyMap.put("is_online_version", isOnlineVersion);
        bodyMap.put("world_rank_version", worldRankVersion);
        bodyMap.put("rank_list",JSON.parse(rankListJson));
        String bodyStr = JSON.toJSONString(bodyMap);

        Request request = new Request.Builder()
                .url("https://webcast.bytedance.com/api/gaming_con/world_rank/upload_rank_list")
                .addHeader("Content-Type", "application/json")
                .addHeader("X-Token", token)
                .post(
                        okhttp3.RequestBody.create(
                                MediaType.parse("application/json; charset=utf-8"),
                                bodyStr
                        )
                )
                .build();
        try {
            Response httpResponse = client.newCall(request).execute();
            if (!httpResponse.isSuccessful()) {
                log.error("上传世界榜单列表数据失败，HTTP响应码: {}", httpResponse.code());
                response.failure("上传世界榜单列表数据，HTTP响应码: " + httpResponse.code());
                return response;
            }
            String responseBody = httpResponse.body().string();
            JSONObject jsonResponse = JSON.parseObject(responseBody);
            // 判断 errcode
            int errcode = jsonResponse.getInteger("errcode");
            if (errcode == 0) {
                response.success("上传世界榜单列表数据成功");
            } else {
                String errmsg = jsonResponse.getString("errmsg");
                log.error("上传世界榜单列表数据失败，错误信息: {}", errmsg);
                response.failure(errmsg);
            }
        } catch (IOException e) {
            log.error("上传世界榜单列表数据失败, e: ", e);
        }

        return response;
    }


    /**
     * 上报用户世界榜单的累计战绩
     * {
     *     "user_list": [
     *        {"score":101,"winning_streak_count":1,"rank":2,"open_id":"8P0gagOFad","winning_points":12}
     *     ]
     * }
     * @param httpRequest
     * @return
     */
    @PostMapping(path = "/upload_user_result")
    public JsonResponse uploadUserResult(HttpServletRequest httpRequest){
        JsonResponse response = new JsonResponse();
        String token = getAccessToken();
        OkHttpClient client = new OkHttpClient();

        String worldRankVersion = (String)myRedisService.getValue("world_rank_version_" + appId);
        if(worldRankVersion == null){
            response.failure("世界榜单未设置，请先调用接口/set_valid_version，设置世界榜单");
            return response;
        }

        // 从请求体中获取 rank_list 参数
        StringBuilder jsonBuilder = new StringBuilder();
        try (BufferedReader reader = httpRequest.getReader()) {
            String line;
            while ((line = reader.readLine()) != null) {
                jsonBuilder.append(line);
            }
        } catch (IOException e) {
            response.failure("json数据不正确");
            return response;
        }


        String requestBody = jsonBuilder.toString();
        if (requestBody.isEmpty()) {
            response.failure("请求体不能为空，未传递 JSON 数据");
            return response;
        }
        JSONObject requestJson = JSON.parseObject(requestBody);
        String rankListJson = requestJson.getString("user_list");
        if (rankListJson == null || rankListJson.isEmpty()) {
            response.failure("缺少用户累计战绩数据列表");
            return response;
        }

        Map<String, Object> bodyMap = new HashMap<>();
        bodyMap.put("app_id", appId);
        bodyMap.put("is_online_version", isOnlineVersion);
        bodyMap.put("world_rank_version", worldRankVersion);
        bodyMap.put("user_list",JSON.parse(rankListJson));
        String bodyStr = JSON.toJSONString(bodyMap);

        Request request = new Request.Builder()
                .url("https://webcast.bytedance.com/api/gaming_con/world_rank/upload_user_result")
                .addHeader("Content-Type", "application/json")
                .addHeader("X-Token", token)
                .post(
                        okhttp3.RequestBody.create(
                                MediaType.parse("application/json; charset=utf-8"),
                                bodyStr
                        )
                )
                .build();
        try {
            Response httpResponse = client.newCall(request).execute();
            if (!httpResponse.isSuccessful()) {
                log.error("上传用户世界榜单的累计战绩失败，HTTP响应码: {}", httpResponse.code());
                response.failure("上传用户世界榜单的累计战绩数据，HTTP响应码: " + httpResponse.code());
                return response;
            }
            String responseBody = httpResponse.body().string();
            JSONObject jsonResponse = JSON.parseObject(responseBody);
            // 判断 errcode
            int errcode = jsonResponse.getInteger("errcode");
            if (errcode == 0) {
                response.success("上传用户世界榜单的累计战绩成功");
            } else {
                String errmsg = jsonResponse.getString("errmsg");
                log.error("上传用户世界榜单的累计战绩失败，错误信息: {}", errmsg);
                response.failure(errmsg);
            }
        } catch (IOException e) {
            log.error("上传用户世界榜单的累计战绩失败, e: ", e);
        }

        return response;
    }


    /**
     * 完成用户世界榜单的累计战绩上报
     * {"app_id":"tt411d37a0dxxxxx","world_rank_version":"1722239345","is_online_version":false,"complete_time":1722239345}
     * @param httpRequest
     * @return
     */
    @PostMapping(path = "/complete_upload_user_result")
    public JsonResponse completeUploadUserResult(HttpServletRequest httpRequest){
        JsonResponse response = new JsonResponse();
        String token = getAccessToken();
        OkHttpClient client = new OkHttpClient();

        String worldRankVersion = (String)myRedisService.getValue("world_rank_version_" + appId);
        if(worldRankVersion == null){
            response.failure("世界榜单未设置，请先调用接口/set_valid_version，设置世界榜单");
            return response;
        }


        Map<String, Object> bodyMap = new HashMap<>();
        bodyMap.put("app_id", appId);
        bodyMap.put("is_online_version", isOnlineVersion);
        bodyMap.put("world_rank_version", worldRankVersion);
        bodyMap.put("complete_time",System.currentTimeMillis() / 1000);
        String bodyStr = JSON.toJSONString(bodyMap);

        Request request = new Request.Builder()
                .url("https://webcast.bytedance.com/api/gaming_con/world_rank/complete_upload_user_result")
                .addHeader("Content-Type", "application/json")
                .addHeader("X-Token", token)
                .post(
                        okhttp3.RequestBody.create(
                                MediaType.parse("application/json; charset=utf-8"),
                                bodyStr
                        )
                )
                .build();
        try {
            Response httpResponse = client.newCall(request).execute();
            if (!httpResponse.isSuccessful()) {
                log.error("完成用户世界榜单的累计战绩上报失败，HTTP响应码: {}", httpResponse.code());
                response.failure("完成用户世界榜单的累计战绩上报失败，HTTP响应码: " + httpResponse.code());
                return response;
            }
            String responseBody = httpResponse.body().string();
            JSONObject jsonResponse = JSON.parseObject(responseBody);
            // 判断 errcode
            int errcode = jsonResponse.getInteger("errcode");
            if (errcode == 0) {
                response.success("完成用户世界榜单的累计战绩上报成功");
            } else {
                String errmsg = jsonResponse.getString("errmsg");
                log.error("完成用户世界榜单的累计战绩上报失败，错误信息: {}", errmsg);
                response.failure(errmsg);
            }
        } catch (IOException e) {
            log.error("完成用户世界榜单的累计战绩上报失败, e: ", e);
        }

        return response;
    }


    /**
     * 同步对局状态
     *{
     *     "round_id": 23,
     *     "room_id": "78273162632",
     *     "app_id": "tt411d37a0dxxxxx",
     *     "anchor_open_id": "UhJKbtCg3N",
     *     "start_time": 1722239345,
     *     "end_time": 1722239345,
     *     "status": 2,
     *     "group_result_list": [
     *         {
     *             "group_id": "test-01",
     *             "result": 1
     *         }
     *     ]
     * }
     * @param httpRequest
     * @return
     */
    @PostMapping(path = "/sync_status")
    public JsonResponse syncStatus(HttpServletRequest httpRequest){
        JsonResponse response = new JsonResponse();
        String token = getAccessToken();
        OkHttpClient client = new OkHttpClient();



        // 从请求体中获取 rank_list 参数
        StringBuilder jsonBuilder = new StringBuilder();
        try (BufferedReader reader = httpRequest.getReader()) {
            String line;
            while ((line = reader.readLine()) != null) {
                jsonBuilder.append(line);
            }
        } catch (IOException e) {
            response.failure("json数据不正确");
            return response;
        }


        String requestBody = jsonBuilder.toString();
        if (requestBody.isEmpty()) {
            response.failure("请求体不能为空，未传递 JSON 数据");
            return response;
        }
        JSONObject requestJson = JSON.parseObject(requestBody);
        String round_id = requestJson.getString("round_id");
        String start_time = requestJson.getString("start_time");
        if (round_id == null || round_id.isEmpty()) {
            response.failure("缺少round_id");
            return response;
        }
        if (start_time == null || start_time.isEmpty()) {
            response.failure("缺少start_time");
            return response;
        }
        String end_time = requestJson.getString("end_time");
        String group_result_list = requestJson.getString("group_result_list");
        if(end_time != null){
            if (group_result_list == null || group_result_list.isEmpty()) {
                response.failure("缺少group_result_list");
                return response;
            }
        }
        String status = requestJson.getString("status");


        // 直播间id
        String roomID = httpRequest.getHeader("X-Room-ID");
        // 主播id
        String anchorOpenID = httpRequest.getHeader("X-Anchor-OpenID");


        Map<String, Object> bodyMap = new HashMap<>();
        bodyMap.put("anchor_open_id", anchorOpenID);
        bodyMap.put("app_id", appId);
        bodyMap.put("room_id",roomID);
        bodyMap.put("round_id",round_id);
        bodyMap.put("start_time",start_time);
        if(end_time != null){
            bodyMap.put("end_time",end_time);
            bodyMap.put("group_result_list",group_result_list);
        }
        bodyMap.put("start_time",start_time);
        bodyMap.put("status",status);

        String bodyStr = JSON.toJSONString(bodyMap);

        Request request = new Request.Builder()
                .url("https://webcast.bytedance.com/api/gaming_con/round/sync_status")
                .addHeader("Content-Type", "application/json")
                .addHeader("X-Token", token)
                .post(
                        okhttp3.RequestBody.create(
                                MediaType.parse("application/json; charset=utf-8"),
                                bodyStr
                        )
                )
                .build();
        try {
            Response httpResponse = client.newCall(request).execute();
            if (!httpResponse.isSuccessful()) {
                log.error("同步对局状态失败，HTTP响应码: {}", httpResponse.code());
                response.failure("同步对局状态失败，HTTP响应码: " + httpResponse.code());
                return response;
            }
            String responseBody = httpResponse.body().string();
            JSONObject jsonResponse = JSON.parseObject(responseBody);
            // 判断 errcode
            int errcode = jsonResponse.getInteger("errcode");
            if (errcode == 0) {
                response.success("同步对局状态成功");
            } else {
                String errmsg = jsonResponse.getString("errmsg");
                log.error("同步对局状态失败，错误信息: {}", errmsg);
                response.failure(errmsg);
            }
        } catch (IOException e) {
            log.error("同步对局状态失败, e: ", e);
        }

        return response;
    }


    /**
     * 上报用户对局数据
     * {
     *     "anchor_open_id": "R31PlZy6fL",
     *     "room_id": "1003434343",
     *     "user_list": [
     *         {
     *             "rank": 12,
     *             "score": 322,
     *             "winning_streak_count": 1232,
     *             "winning_points": 4223,
     *             "round_result": 1,
     *             "open_id": "i4WwTDWUGP",
     *             "group_id": "test-01"
     *         }
     *     ],
     *     "app_id": "tt411d37a0dxxxxx",
     *     "round_id": 213
     * }
     * @param httpRequest
     * @return
     */
    @PostMapping(path = "/upload_user_result_game")
    public JsonResponse uploadUserResultGame(HttpServletRequest httpRequest){
        JsonResponse response = new JsonResponse();
        String token = getAccessToken();
        OkHttpClient client = new OkHttpClient();


        // 从请求体中获取 rank_list 参数
        StringBuilder jsonBuilder = new StringBuilder();
        try (BufferedReader reader = httpRequest.getReader()) {
            String line;
            while ((line = reader.readLine()) != null) {
                jsonBuilder.append(line);
            }
        } catch (IOException e) {
            response.failure("json数据不正确");
            return response;
        }


        String requestBody = jsonBuilder.toString();
        if (requestBody.isEmpty()) {
            response.failure("请求体不能为空，未传递 JSON 数据");
            return response;
        }
        JSONObject requestJson = JSON.parseObject(requestBody);
        String round_id = requestJson.getString("round_id");
        if (round_id == null || round_id.isEmpty()) {
            response.failure("缺少round_id");
            return response;
        }
        String user_list = requestJson.getString("user_list");
        if (user_list == null || user_list.isEmpty()) {
            response.failure("缺少user_list");
            return response;
        }

        // 直播间id
        String roomID = httpRequest.getHeader("X-Room-ID");
        // 主播id
        String anchorOpenID = httpRequest.getHeader("X-Anchor-OpenID");

        Map<String, Object> bodyMap = new HashMap<>();
        bodyMap.put("anchor_open_id", anchorOpenID);
        bodyMap.put("app_id", appId);
        bodyMap.put("room_id",roomID);
        bodyMap.put("round_id",round_id);
        bodyMap.put("user_list",JSON.parse(user_list));
        String bodyStr = JSON.toJSONString(bodyMap);

        Request request = new Request.Builder()
                .url("https://webcast.bytedance.com/api/gaming_con/round/upload_user_result")
                .addHeader("Content-Type", "application/json")
                .addHeader("X-Token", token)
                .post(
                        okhttp3.RequestBody.create(
                                MediaType.parse("application/json; charset=utf-8"),
                                bodyStr
                        )
                )
                .build();
        try {
            Response httpResponse = client.newCall(request).execute();
            if (!httpResponse.isSuccessful()) {
                log.error("上传用户世界榜单的累计战绩失败，HTTP响应码: {}", httpResponse.code());
                response.failure("上传用户世界榜单的累计战绩数据，HTTP响应码: " + httpResponse.code());
                return response;
            }
            String responseBody = httpResponse.body().string();
            JSONObject jsonResponse = JSON.parseObject(responseBody);
            // 判断 errcode
            int errcode = jsonResponse.getInteger("errcode");
            if (errcode == 0) {
                response.success("上传用户世界榜单的累计战绩成功");
            } else {
                String errmsg = jsonResponse.getString("errmsg");
                log.error("上传用户世界榜单的累计战绩失败，错误信息: {}", errmsg);
                response.failure(errmsg);
            }
        } catch (IOException e) {
            log.error("上传用户世界榜单的累计战绩失败, e: ", e);
        }

        return response;
    }



    /**
     * 上报对局榜单列表
     *{
     *     "app_id": "tt411d37a0dxxxxx",
     *     "round_id": 12,
     *     "anchor_open_id": "a7Co8Q3M2v",
     *     "room_id": "7867864325642",
     *     "rank_list": [
     *         {
     *             "rank": 12,
     *             "score": 212,
     *             "winning_streak_count": 21312,
     *             "winning_points": 2132,
     *             "round_result": 1,
     *             "open_id": "B0AIsWiHa7",
     *             "group_id": "red"
     *         }
     *     ]
     * }
     * @param httpRequest
     * @return
     */
    @PostMapping(path = "/upload_rank_list_game")
    public JsonResponse uploadRankListGame(HttpServletRequest httpRequest){
        JsonResponse response = new JsonResponse();
        String token = getAccessToken();
        OkHttpClient client = new OkHttpClient();


        // 从请求体中获取 rank_list 参数
        StringBuilder jsonBuilder = new StringBuilder();
        try (BufferedReader reader = httpRequest.getReader()) {
            String line;
            while ((line = reader.readLine()) != null) {
                jsonBuilder.append(line);
            }
        } catch (IOException e) {
            response.failure("json数据不正确");
            return response;
        }


        String requestBody = jsonBuilder.toString();
        if (requestBody.isEmpty()) {
            response.failure("请求体不能为空，未传递 JSON 数据");
            return response;
        }
        JSONObject requestJson = JSON.parseObject(requestBody);
        String round_id = requestJson.getString("round_id");
        if (round_id == null || round_id.isEmpty()) {
            response.failure("缺少round_id");
            return response;
        }
        String rank_list = requestJson.getString("rank_list");
        if (rank_list == null || rank_list.isEmpty()) {
            response.failure("缺少rank_list");
            return response;
        }

        // 直播间id
        String roomID = httpRequest.getHeader("X-Room-ID");
        // 主播id
        String anchorOpenID = httpRequest.getHeader("X-Anchor-OpenID");

        Map<String, Object> bodyMap = new HashMap<>();
        bodyMap.put("anchor_open_id", anchorOpenID);
        bodyMap.put("app_id", appId);
        bodyMap.put("room_id",roomID);
        bodyMap.put("round_id",round_id);
        bodyMap.put("rank_list",JSON.parse(rank_list));
        String bodyStr = JSON.toJSONString(bodyMap);

        Request request = new Request.Builder()
                .url("https://webcast.bytedance.com/api/gaming_con/round/upload_rank_list")
                .addHeader("Content-Type", "application/json")
                .addHeader("X-Token", token)
                .post(
                        okhttp3.RequestBody.create(
                                MediaType.parse("application/json; charset=utf-8"),
                                bodyStr
                        )
                )
                .build();
        try {
            Response httpResponse = client.newCall(request).execute();
            if (!httpResponse.isSuccessful()) {
                log.error("上报对局榜单列表失败，HTTP响应码: {}", httpResponse.code());
                response.failure("上报对局榜单列表，HTTP响应码: " + httpResponse.code());
                return response;
            }
            String responseBody = httpResponse.body().string();
            JSONObject jsonResponse = JSON.parseObject(responseBody);
            // 判断 errcode
            int errcode = jsonResponse.getInteger("errcode");
            if (errcode == 0) {
                response.success("上报对局榜单列表成功");
            } else {
                String errmsg = jsonResponse.getString("errmsg");
                log.error("上报对局榜单列表失败，错误信息: {}", errmsg);
                response.failure(errmsg);
            }
        } catch (IOException e) {
            log.error("上报对局榜单列表失败, e: ", e);
        }

        return response;
    }




    /**
     * 完成上报对局榜单列表
     *{
     *
     *     "app_id": "tt411d37a0dxxxxx",
     *     "round_id": 1232,
     *     "anchor_open_id": "a84NH6Okrb",
     *     "room_id": "7827382738223"
     * }
     * @param httpRequest
     * @return
     */
    @PostMapping(path = "/complete_upload_user_result_game")
    public JsonResponse completeUploadUserResultGame(HttpServletRequest httpRequest){
        JsonResponse response = new JsonResponse();
        String token = getAccessToken();
        OkHttpClient client = new OkHttpClient();


        // 从请求体中获取 rank_list 参数
        StringBuilder jsonBuilder = new StringBuilder();
        try (BufferedReader reader = httpRequest.getReader()) {
            String line;
            while ((line = reader.readLine()) != null) {
                jsonBuilder.append(line);
            }
        } catch (IOException e) {
            response.failure("json数据不正确");
            return response;
        }


        String requestBody = jsonBuilder.toString();
        if (requestBody.isEmpty()) {
            response.failure("请求体不能为空，未传递 JSON 数据");
            return response;
        }
        JSONObject requestJson = JSON.parseObject(requestBody);
        String round_id = requestJson.getString("round_id");
        if (round_id == null || round_id.isEmpty()) {
            response.failure("缺少round_id");
            return response;
        }


        // 直播间id
        String roomID = httpRequest.getHeader("X-Room-ID");
        // 主播id
        String anchorOpenID = httpRequest.getHeader("X-Anchor-OpenID");

        Map<String, Object> bodyMap = new HashMap<>();
        bodyMap.put("anchor_open_id", anchorOpenID);
        bodyMap.put("app_id", appId);
        bodyMap.put("room_id",roomID);
        bodyMap.put("round_id",round_id);
        bodyMap.put("complete_time",System.currentTimeMillis() / 1000);
        String bodyStr = JSON.toJSONString(bodyMap);

        Request request = new Request.Builder()
                .url("https://webcast.bytedance.com/api/gaming_con/round/complete_upload_user_result")
                .addHeader("Content-Type", "application/json")
                .addHeader("X-Token", token)
                .post(
                        okhttp3.RequestBody.create(
                                MediaType.parse("application/json; charset=utf-8"),
                                bodyStr
                        )
                )
                .build();
        try {
            Response httpResponse = client.newCall(request).execute();
            if (!httpResponse.isSuccessful()) {
                log.error("完成上报对局榜单列表失败，HTTP响应码: {}", httpResponse.code());
                response.failure("完成上报对局榜单列表，HTTP响应码: " + httpResponse.code());
                return response;
            }
            String responseBody = httpResponse.body().string();
            JSONObject jsonResponse = JSON.parseObject(responseBody);
            // 判断 errcode
            int errcode = jsonResponse.getInteger("errcode");
            if (errcode == 0) {
                response.success("完成上报对局榜单列表成功");
            } else {
                String errmsg = jsonResponse.getString("errmsg");
                log.error("完成上报对局榜单列表失败，错误信息: {}", errmsg);
                response.failure(errmsg);
            }
        } catch (IOException e) {
            log.error("完成上报对局榜单列表失败, e: ", e);
        }

        return response;
    }



    /**
     * 获取token
     * @return
     */
    private String getAccessToken() {
        // 获取token
        String token = (String) myRedisService.getValue("token_" + appId);
        if (token != null) {
            return token; // 如果token存在，直接返回
        }

        String url = "https://developer.toutiao.com/api/apps/v2/token";
        String grantType = "client_credential";

        // 构建请求体
        JSONObject requestBody = new JSONObject();
        requestBody.put("appid", appId);
        requestBody.put("secret", appSecret);
        requestBody.put("grant_type", grantType);

        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder()
                .url(url)
                .addHeader("Content-Type", "application/json")
                .post(okhttp3.RequestBody.create(
                        MediaType.get("application/json; charset=utf-8"),
                        requestBody.toString()
                ))
                .build();

        try (Response response = client.newCall(request).execute()) {
            if (!response.isSuccessful()) {
                log.error("获取access_token失败，HTTP响应码: {}", response.code());
                return null;
            }

            String responseBody = response.body().string();
            JSONObject jsonResponse = JSON.parseObject(responseBody);

            // 判断 err_no
            if (jsonResponse.getInteger("err_no") == 0) {
                // 成功，获取 access_token
                String newToken = jsonResponse.getJSONObject("data").getString("access_token");
                myRedisService.setValueExpire("token_" + appId, newToken,3600);
                return newToken;
            } else {
                log.error("获取access_token失败，错误信息: {}", jsonResponse.getString("err_tips"));
                return null;
            }
        } catch (IOException e) {
            log.error("获取access_token异常: {}", e.getMessage(), e);
            return null;
        }
    }

}
